#
# Class that renders the time from the calendar on the web UI.
#
# OR: use pyjamas and talk ajax immediately, refresh is easy
#
#
# BUG: Should display the date range and days we're actually using.  Bug is that we don't start on a monday.
# BUG: should re-select the currently selected month dropdown (is there something that does this for me, gack?).

import gdata.calendar
import gdata.calendar.service
import gdata.service
import atom.service
import gdata.alt.appengine
import atom
import atom.url
import wsgiref.handlers
import cgi
import urllib
from dateparser import *

from timetallier import *


class TimeDisplayer(object):
  def __init__(self, request, response, calendarClient):
    self.calendarClient = calendarClient
    self.response = response
    self.request = request

  def commonHtml(self):
    self.response.out.write("""
    
<head>
<style type='text/css'>

    .hourTable {
      border: thin solid;
      border-collapse: collapse;
    }
    
    .hourTable td {
      padding: 6px;
    }

</style>
</head>
""")

  def showGoogleCalendarInIFrame(self, calendarUser):
    # TODO: put this inside a disclosure panel, so I can hide it easily. 
    
    self.response.out.write("""
    
      <iframe src="//www.google.com/calendar/render?mode=WEEK&amp;height=700&amp;wkst=2&amp;color=%23A32929&amp"
        style=" border:solid 1px #777 "
        width="100%"
        height="700"
        frameborder="0"
        scrolling="no">
        
      </iframe>
      <br/>
      """)
      
  def showTools(self, calendarFeed, selectedCalendar):
    self.response.out.write("""
    
<form action='loginFromGoogle' method='get'>
  Calendar: <select name='calendar'>
  
    """)
    
    for index, calendar in enumerate(calendarFeed.entry):
      calendarTitle = calendar.title.text
      selected = ""
      if calendarTitle == selectedCalendar:
        selected = "selected='selected'"
      self.response.out.write("<option value='%s' %s>%s</option>" % (calendarTitle, selected, calendarTitle))
    
    self.response.out.write("""
    </select>
    
    <br />
    
    Month:
    <select name='month'>
      <option value="1">January</option>
      <option value="2">February</option>
      <option value="3">March</option>
      <option value="4">April</option>
      <option value="5">May</option>
      <option value="6">June</option>
      <option value="7">July</option>
      <option value="8">August</option>
      <option value="9">September</option>
      <option value="10">October</option>
      <option value="11">November</option>
      <option value="12">December</option>
    </select>
    
    <br />
    
    <input type="submit" value="Update" />
</form>

    """)
    
    
  def processCall(self):
    
    self.commonHtml()
    
    allCalendarsFeed = self.calendarClient.GetAllCalendarsFeed()
    
    selectedCalendar = None
    if "calendar" in self.request.params:
      selectedCalendar = self.request.params["calendar"]
      
    self.showGoogleCalendarInIFrame(selectedCalendar)
      
    self.showTools(allCalendarsFeed, selectedCalendar)
    
    # Don't try to show selected calendar stuff if it's not been selected
    if not selectedCalendar:
      return
    
    selectedCalendar = self.request.params["calendar"]
    self.showCalendarTotals(allCalendarsFeed, selectedCalendar)
      
  def showCalendarTotals(self, allCalendarsFeed, selectedCalendarName):
    #FIXME: allow years here too
    user = None
    for index, calendar in enumerate(allCalendarsFeed.entry):
      if selectedCalendarName == calendar.title.text:
        user = urllib.unquote(calendar.link[0].href.split("/")[-3])
          
    if not user:
      raise Exception("No calendar found for: " + selectedCalendarName)
    
    requestedMonth = int(self.request.params.get("month", datetime.now().month))
    
    now = datetime.now()
    startDate = datetime(now.year, requestedMonth, 1)
    
    self.response.out.write("Showing results for: " + startDate.strftime("%B, %Y"))
      
    calendarEventQuery = gdata.calendar.service.CalendarEventQuery(user, "private", "full")
    calendarEventQuery.start_min = '2009-%02d-01' % requestedMonth
    calendarEventQuery.start_max = '2009-%02d-31' % requestedMonth
    calendarEventQuery.orderby = "starttime"
    calendarEventQuery.singleevents = "true"
    calendarEventQuery["max-results"] = "100"
    timeTallier = TimeTallier(now.year, requestedMonth)
    feed = self.calendarClient.CalendarQuery(calendarEventQuery)
    self.response.out.write("<br/>")
    # Tally up times in the time tallier
    for i, an_event in zip(xrange(len(feed.entry)), feed.entry):
      #self.response.out.write("%s <br/> " % dir(an_event))
      for when in an_event.when:
        dateParser = DateParser()
        endTime = dateParser.parseDate(when.end_time)
        startTime = dateParser.parseDate(when.start_time)
        
        # TODO: kick out times we don't expect - test this!
        if (startTime.month != startDate.month):
          continue
        
        self.response.out.write("day: %s, start: %s, end: %s, in: %s <br/> " % (startTime.day - 1, startTime, endTime, an_event.title))
        timeTallier.addTimeBlock(startTime.day - 1, startTime, endTime)
      
      
    # Print them out
    # TODO: it'd be nice to know which actual day of the month each item corresponded to.
    self.printTimesAndSums(timeTallier.getWeeks())
    
    self.response.out.write("<br/>CSV Tally:<br/>")
    self.printTimesAsCSV(timeTallier.getWeeks())
    
  def printTimesAndSums(self, weeks):
    self.response.out.write("<table border='1' class='hourTable'>")
    self.printTableRow(["Week", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "Total"])
    weekIndex = 1
    for week in weeks:
      
      weeklySum = 0.0
      for day in week:
        if day != None:
          weeklySum += day.total
        
      self.printTableRow(["week: %d" % weekIndex] + \
                         [str(day) for day in week] + \
                         ["Total: %1.2f hours" % weeklySum])
      
      weekIndex += 1
      
    self.response.out.write("</table>")

  def getDayValueForCSV(self, dayTotal):
    if dayTotal:
      return "%1.2f" % dayTotal.total
    else:
      return "0.0"
    
  def printTimesAsCSV(self, weeks):
    self.response.out.write("<table border='1' class='hourTable'>")
    for week in weeks:
      dayStrValues = map(self.getDayValueForCSV, week) # Filter out ones that are None
      self.printTableRow(dayStrValues)
      
    self.response.out.write("</table>")
      
  def printTableRow(self, values):
    self.response.out.write("<tr>")
    
    for value in values:
      self.response.out.write("<td>%s</td>" % value)
    
    self.response.out.write("</tr>")